home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 2
/
Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso
/
Aminet
/
mus
/
play
/
MP132src.lha
/
ptsplay.asm
< prev
next >
Wrap
Assembly Source File
|
1992-09-14
|
42KB
|
1,585 lines
* MultiPlayer
* Copyright (C) 1992 Bryan Ford
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* I (the author of MultiPlayer) can be contacted on the Internet at
* "bryan.ford@m.cc.utah.edu". See "Player.doc" for other addresses.
*
* This Protracker playroutine is very heavily modified from the one
* supplied with Protracker 1.1b, 1.2, and 2.1. (All of these versions
* used the same player code.) In particular, it uses the NotePlayer
* system to play notes instead of going to the hardware. It also
* contains many bug fixes and compatibility enhancements (such as the
* ability to play 15-instrument modules).
*
* Note that while most previous MutantTracker play routines were
* public domain, this version is expressly taken out of the public
* domain and brought under the GNU General Public License.
*
* $Id: ptsplay.asm,v 5.5 92/09/14 18:42:54 BAF Exp $
*
; This is THE ONLY 100% FIXED VERSION of the PROTRACKER PLAYROUTINE!!!
;
; Please spread this WORLDWIDE as we are are fed up with utilities
; using the bugged playroutine supplied with the original Protracker
; release archieve.
;
; Some utils I hope to see with the 100% FIXED playroutine SOON:
;
; PTPlayer -command by TSM/Vision
; Chameleon Music Player (ChamPlay)
; Noiseplayer by TRSI
;
; ...and all other utils playing PROTRACKER MODULES!!!
;
; ///BUG/// -*- N E T W O R K -*-
;
; Cool musicians write to: Noiseless
; Box 5036
; 6021 Alesund
; Norway
;******************************************** ; 100% FIXED VERSION
;* ----- Protracker V1.1B Playroutine ----- *
;* Lars "Zap" Hamre/Amiga Freelancers 1991 *
;* Bekkeliveien 10, N-2010 STRØMMEN, Norway *
;********************************************
; VBlank Version 2.01:
; Call mt_init to initialize the routine, then call mt_music on
; each vertical blank (50 Hz). To end the song and turn off all
; voices, call mt_end.
; This playroutine is not very fast, optimized or well commented,
; but all the new commands in PT1.1A should work.
; If it's not good enough, you'll have to change it yourself.
; We'll try to write a faster routine soon...
; Changes from V1.0C playroutine:
; - Vibrato depth changed to be compatible with Noisetracker 2.0.
; You'll have to double all vib. depths on old PT modules.
; - Funk Repeat changed to Invert Loop.
; - Period set back earlier when stopping an effect.
include "exec/types.i"
include "exec/ables.i"
include "exec/execbase.i"
include "hardware/custom.i"
include "player.i"
include "bry/macros.i"
_intena equ (CUSTOM+intena)
NoteInfo equ $00
NoteInit equ $04
NoteFinish equ $08
NoteStart equ $0c
NoteStop equ $10
NoteFreqVol equ $14
NoteFreq equ $18
NoteVol equ $1c
xref modmem,modend,intsongpos,intrepeat,getfreqmodspeed,hookfunc
xref ntgetsongname,ntgetsongauthor,intflashnote,intflashsample,intflashscroll,changetintcia
xref scrollmod,scrolllines,notetab,modflags,filter,modtype
xdef ntstart,ptfilter
code text
ntstart:
ori.b #MTF_PROTRACKER!MTF_FILTER,modtype(a4)
plstartret 9$
cnop 0,4
dc.l gmod_GetScroll+4
9$ gmodbra init ; InitMusic
gmodbra start ; StartMusic
gmodbra mt_stop ; StopMusic
gmodbra fin ; EndMusic
gmodbra noteplayersave ; NotePlayer
gmodq 1 ; ContinueMusic
gmodnop
gmodnop
gmodnop
gmodnop
gmodnop
gmodnop
gmodnop
gmodbra ntgetsongname ; GetSongName
gmodbra ntgetsongauthor ; GetSongAuthor
gmodbra getfreqmodspeed ; GetFrequency
gmodbra mt_music ; TimerTick
gmodbra \makername ; GetMakerName
gmodbra \hook ; Hook
gmodbra \jump
gmodnop
move.l scroll(pc),d0
rts
\hook
move.l #GMODHF_REPEAT!GMODHF_SEQUENCE,d0
rts
\makername
lea name(pc),a0
move.l a0,d0
rts
\jump
DISABLE a0
clr.w mt_PatternPos
clr.b mt_PBreakPos
clr.b mt_PosJumpFlag
move.L mt_SongDataPtr(PC),A0
suba.w seqadj(pc),a0
moveq #0,d0
move.b $3b6(a0),d0
cmp.l d0,d1
blo.s \jumpok
cq d1
\jumpok
move.b d1,mt_SongPos
exg d1,d0
jsr intsongpos
ENABLE a0
moveq #1,d1
rts
n_note EQU 0 ; W
n_cmd EQU 2 ; W
n_cmdlo EQU 3 ; B
n_start EQU 4 ; L
n_length EQU 8 ; W
n_loopstart EQU 10 ; L
n_replen EQU 14 ; W
n_period EQU 16 ; W
n_finetune EQU 18 ; B
n_volume EQU 19 ; B
n_dmabit EQU 20 ; W
n_toneportdirec EQU 22 ; B
n_toneportspeed EQU 23 ; B
n_wantedperiod EQU 24 ; W
n_vibratocmd EQU 26 ; B
n_vibratopos EQU 27 ; B
n_tremolocmd EQU 28 ; B
n_tremolopos EQU 29 ; B
n_wavecontrol EQU 30 ; B
n_glissfunk EQU 31 ; B
n_sampleoffset EQU 32 ; B
n_pattpos EQU 33 ; B
n_loopcount EQU 34 ; B
n_funkoffset EQU 35 ; B
n_wavestart EQU 36 ; L
n_reallength EQU 40 ; W
n_channelno EQU 42 ; W
n_realper EQU 44 ; W
n_realvol EQU 46 ; W
noteplayersave
move.l a0,noteplayer
moveq #1,d0
rts
init movem.l d2-d3/a2-a3,-(sp)
move.l noteplayer(pc),a1 ; Initialize the NotePlayer
sub.l a0,a0
moveq #4,d0
jsr NoteInit(a1)
tst.l d0
bnz initout
clr.l scroll
move.l modmem,a0 ;
MOVE.L A0,mt_SongDataPtr
move.l modend,a3
subq.l #4,a3
moveq #0,d0 ; Check for old modules
moveq #0,d1
move.w #31-1,-(sp)
tst.b $1d6(a0)
beq.s 1$
cmp.b #1,$1f3(a0)
beq.s 1$
cmp.l #'M.K.',$438(a0)
beq.s 1$
move.w #$1e0,d0
move.w #$1e4,d1
move.w #15-1,(sp)
1$ move.w d0,seqadj
move.w d1,blkadj
MOVE.L A0,A1
LEA 952(A1),A1
suba.w d0,a1
movem.l d0-d1/a0-a1,-(sp) ; Set MultiPlayer's position display
moveq #0,d0
moveq #0,d1
move.b -2(a1),d1
jsr intsongpos
movem.l (sp)+,d0-d1/a0-a1
MOVEQ #127,D0
MOVEQ #0,D1
mtloop MOVE.L D1,D2
SUBQ.W #1,D0
mtloop2 MOVE.B (A1)+,D1
CMP.B D2,D1
BGT.S mtloop
DBRA D0,mtloop2
ADDQ.B #1,D2
LEA mt_SampleStarts(PC),A1
ASL.L #8,D2
ASL.L #2,D2
ADD.L #1084,D2
ADD.L A0,D2
MOVE.L D2,A2
suba.w blkadj(pc),a2 ;
move.w (sp)+,d0
mtloop3
* Clear the first four bytes of the sample. This piece of code has caused a great deal of grief for
* many people before it included this end-of-module check. (Just ask Ed Mackey. :-) ) Most
* MutantTracker modules don't use all the available instrument slots, so the last instruments are
* empty (zero length). However, in unmodified player source code, this code keeps plowing on through,
* clearing the first four bytes _past_ the end of the module. This is usually no problem when the
* module is part of a game or demo or something, but can cause weird memory errors when the module's
* memory is allocated dynamically to its exact length.
*
* Oh yeah...Why clear the first four bytes? Protracker and most other closely related mutants handle
* non-repeating samples by simply setting the repeat position and length so that, after the sample is
* played once, it plays the first four bytes over and over forever (until another sample is started).
* If the first four bytes weren't zero, then you'd hear a weird buzzy sound at the end of any non-
* repeating sample.
*
* Most new tracker modules come with the first four bytes of each sample already cleared, so this isn't
* necessary for them. It's mainly for older modules.
cmp.l a2,a3
blt.s \inrange
clr.l (a2)
\inrange
MOVE.L A2,(A1)+
MOVEQ #0,D1
MOVE.W 42(A0),D1
bz.b \nosample
* This little hack is for old-style (15-instrument) modules that occasionally had 'repeat' stored as
* number of bytes instead of words. We assume that this is the case if repeat+replen > length.
* This should be safe for all new modules, since repeat+replen is never supposed to be bigger than
* the sample size. However, it may not detect all cases of this syndrome, because repeat+replen
* is allowed to be smaller (even much smaller) than the sample length (i.e. when some of the sample
* is not used).
move.w 42+4(a0),d3
add.w 42+6(a0),d3
cmp.w d1,d3
bls.b \repeat_ok
lsr.w 42+4(a0)
\repeat_ok
ASL.L #1,D1
move.l d1,d2
ADD.l d1,a2
\nosample
ADD.L #30,A0
DBRA D0,mtloop3
addq.l #4,a3 ; See if the last sample is a scrolltext
cmp.l a2,a3
blt.b \noscroll
move.l d2,d0
cq d1
\more
tst.b -(a2)
bpl.b \lower
addq.l #1,d1
\lower
subq.l #1,d0
bhi.b \more
lsl.l #2,d1 ; If 3/4 or more of the bytes are <$80, assume it's ASCII
cmp.l d1,d2
blo.b \noscroll
clr.b -1(a2,d2.l) ; Null-terminate the scroll text
addq #4,a2 ; Get past the four bytes we clobbered
move.l a2,scroll
\noscroll
moveq #0,d0
initout
movem.l (sp)+,d2-d3/a2-a3
rts
start
clr.w scrollmod ; Note scroller information
moveq #1,d0
bsr initfilter
clr.l mt_chan1temp+n_realper
clr.l mt_chan2temp+n_realper
clr.l mt_chan3temp+n_realper
clr.l mt_chan4temp+n_realper
MOVE.B #6,mt_speed
CLR.B mt_counter
CLR.B mt_SongPos
CLR.W mt_PatternPos
cq d0
cq d1
bsr findnotetab
st.b playing
rts
mt_stop
clr.b playing
rts
fin
move.l noteplayer(pc),a0
jmp NoteFinish(a0)
usevol macro
cmp.w n_realvol(a6),d0
beq.b \usevol\@
movem.l d1-d2/d4/a0-a1,-(sp)
move.w n_channelno(a6),d2
MOVE.W D0,d4
move.w d0,n_realvol(a6)
lsl.w #2,d4
jsr NoteVol(a5)
movem.l (sp)+,d1-d2/d4/a0-a1
\usevol\@:
endm
useper macro
cmp.w n_realper(a6),d0
beq.b \useper\@
movem.l d1-d3/a0-a1,-(sp)
move.w n_channelno(a6),d2
moveq #0,d3
move.w d0,n_realper(a6)
MOVE.W d0,d3
swap d3
jsr NoteFreq(a5)
movem.l (sp)+,d1-d3/a0-a1
\useper\@
endm
* Register conventions:
* d2 = Channel number (not quite yet)
* d5-d7 = Always available
* a5 = NotePlayer
* a6 = chan#temp
mt_music
movem.l d0-d7/a0-a6,-(SP) ;
move.l noteplayer(pc),a5
ADDQ.B #1,mt_counter
MOVE.B mt_counter(PC),D0
CMP.B mt_speed(PC),D0
BLO.S mt_NoNewNote
CLR.B mt_counter
TST.B mt_PattDelTime2
BEQ.S mt_GetNewNote
BSR.S mt_NoNewAllChannels
BRA mt_dskip
mt_NoNewNote
BSR.S mt_NoNewAllChannels
BRA mt_NoNewPosYet
mt_NoNewAllChannels
LEA mt_chan1temp(PC),A6
BSR mt_CheckEfx
LEA mt_chan2temp(PC),A6
BSR mt_CheckEfx
LEA mt_chan3temp(PC),A6
BSR mt_CheckEfx
LEA mt_chan4temp(PC),A6
BRA mt_CheckEfx
mt_GetNewNote
MOVE.L mt_SongDataPtr(PC),A0
LEA 12(A0),A3
LEA 952(A0),A2 ;pattpo
suba.w seqadj(pc),a2
LEA 1084(A0),A0 ;patterndata
suba.w blkadj(pc),a0
MOVEQ #0,D0
MOVEQ #0,D1
MOVE.B mt_SongPos(PC),D0
MOVE.B 0(A2,D0.W),D1
ASL.L #8,D1
ASL.L #2,D1
ADD.W mt_PatternPos(PC),D1
LEA mt_chan1temp(PC),A6
BSR.S mt_PlayVoice
LEA mt_chan2temp(PC),A6
BSR.S mt_PlayVoice
LEA mt_chan3temp(PC),A6
BSR.S mt_PlayVoice
LEA mt_chan4temp(PC),A6
BSR.S mt_PlayVoice
BRA mt_SetDMA
mt_PlayVoice
TST.L (A6)
BNE.S mt_plvskip
BSR mt_PerNop
mt_plvskip
MOVE.L 0(A0,D1.L),(A6)
ADDQ.L #4,D1
MOVEQ #0,D2
MOVE.B n_cmd(A6),D2
AND.B #$F0,D2
LSR.B #4,D2
MOVE.B (A6),D0
AND.B #$F0,D0
OR.B D0,D2
BEQ mt_SetRegs
MOVEQ #0,D3
LEA mt_SampleStarts(PC),A1
MOVE D2,D4
SUBQ.L #1,D2
ASL.L #2,D2
MULU #30,D4
MOVE.L 0(A1,D2.L),n_start(A6)
MOVE.W 0(A3,D4.L),n_length(A6)
MOVE.W 0(A3,D4.L),n_reallength(A6)
MOVE.B 2(A3,D4.L),n_finetune(A6)
MOVE.B 3(A3,D4.L),n_volume(A6)
MOVE.W 4(A3,D4.L),D3 ; Get repeat
push a0/d0-d3/a0 ; BAF - Flash the note on the display
move.w (a6),d0
andi.w #$fff,d0
lea mt_PeriodTable(pc),a0
moveq #-1,d1
1$ addq.w #1,d1
cmp.w (a0)+,d0
blo.b 1$
move.b mt_FlashNotes(pc,d1.w),d1
move.w n_channelno(a6),d0
move.b n_volume(a6),d2
bsr intflashnote
move.l n_start(a6),a0
move.w (a6),d1
andi.w #$fff,d1
move.w n_length(a6),d2
add.w d2,d2
move.w 6(a3,d4.l),d3
add.w d3,d3
bsr intflashsample
pop a0/d0-d3/a0
TST.W D3
BEQ.S mt_NoLoop
MOVE.L n_start(A6),D2 ; Get start
ASL.W #1,D3
ADD.L D3,D2 ; Add repeat
MOVE.L D2,n_loopstart(A6)
MOVE.L D2,n_wavestart(A6)
MOVE.W 4(A3,D4.L),D0 ; Get repeat
ADD.W 6(A3,D4.L),D0 ; Add replen
MOVE.W D0,n_length(A6)
MOVE.W 6(A3,D4.L),n_replen(A6) ; Save replen
BRA.S mt_SetRegsVol
mt_FlashNotes dc.b 0,7,14,21,28,35,42,49,56,64
dc.b 71,78,85,92,99,106,113,120,128,135
dc.b 142,149,156,163,170,177,184,192,199,206
dc.b 213,220,227,234,241,248
mt_NoLoop
MOVE.L n_start(A6),D2
MOVE.L D2,n_loopstart(A6)
MOVE.L D2,n_wavestart(A6)
MOVE.W 6(A3,D4.L),n_replen(A6) ; Save replen
mt_SetRegsVol
MOVEQ #0,D0
MOVE.B n_volume(A6),D0
usevol
mt_SetRegs
MOVE.W (A6),D0
AND.W #$0FFF,D0
BEQ mt_CheckMoreEfx ; If no note
MOVE.W 2(A6),D0
AND.W #$0FF0,D0
CMP.W #$0E50,D0
BEQ.S mt_DoSetFineTune
MOVE.B 2(A6),D0
AND.B #$0F,D0
CMP.B #3,D0 ; TonePortamento
BEQ.S mt_ChkTonePorta
CMP.B #5,D0
BEQ.S mt_ChkTonePorta
CMP.B #9,D0 ; Sample Offset
BNE.S mt_SetPeriod
BSR mt_CheckMoreEfx
BRA.S mt_SetPeriod
mt_DoSetFineTune
BSR mt_SetFineTune
BRA.S mt_SetPeriod
mt_ChkTonePorta
BSR mt_SetTonePorta
BRA mt_CheckMoreEfx
mt_SetPeriod
MOVEM.L D0-D1/A0-A1,-(SP)
MOVE.W (A6),D1
AND.W #$0FFF,D1
tst.b n_finetune(a6)
bz mt_noft
LEA mt_PeriodTable(PC),A1
MOVEQ #0,D0
MOVEQ #36,D2
mt_ftuloop
CMP.W 0(A1,D0.W),D1
BHS.S mt_ftufound
ADDQ.L #2,D0
DBRA D2,mt_ftuloop
mt_ftufound
MOVEQ #0,D1
MOVE.B n_finetune(A6),D1
MULU #36*2,D1
ADD.L D1,A1
MOVE.W 0(A1,D0.W),d1
mt_noft
move.w d1,n_period(A6)
MOVEM.L (SP)+,D0-D1/A0-A1
MOVE.W 2(A6),D0
AND.W #$0FF0,D0
CMP.W #$0ED0,D0 ; Notedelay
BEQ mt_CheckMoreEfx
BTST #2,n_wavecontrol(A6)
BNE.S mt_vibnoc
CLR.B n_vibratopos(A6)
mt_vibnoc
BTST #6,n_wavecontrol(A6)
BNE.S mt_trenoc
CLR.B n_tremolopos(A6)
mt_trenoc
movem.l d1-d4/a0-a1,-(sp)
move.l n_start(a6),a0
moveq #0,d0
move.w n_length(a6),d0
add.l d0,d0
move.l n_loopstart(a6),a1
moveq #0,d1
move.w n_replen(a6),d1
cmp.w #1,d1
bne.b \notone
moveq #0,d1
\notone
add.l d1,d1
move.w n_channelno(a6),d2
moveq #0,d3
move.w n_period(a6),d3
move.w d3,n_realper(a6)
swap d3
moveq #0,d4
move.b n_volume(a6),d4
move.w d4,n_realvol(a6)
lsl.w #2,d4
jsr NoteStart(a5)
movem.l (sp)+,d1-d4/a0-a1
BRA mt_CheckMoreEfx
mt_SetDMA
mt_dskip
ADD.W #16,mt_PatternPos
MOVE.B mt_PattDelTime,D0
BEQ.S mt_dskc
MOVE.B D0,mt_PattDelTime2
CLR.B mt_PattDelTime
mt_dskc TST.B mt_PattDelTime2
BEQ.S mt_dska
SUBQ.B #1,mt_PattDelTime2
BEQ.S mt_dska
SUB.W #16,mt_PatternPos
mt_dska TST.B mt_PBreakFlag
BEQ.S mt_nnpysk
SF mt_PBreakFlag
MOVEQ #0,D0
MOVE.B mt_PBreakPos(PC),D0
CLR.B mt_PBreakPos
LSL.W #4,D0
MOVE.W D0,mt_PatternPos
mt_nnpysk
CMP.W #1024,mt_PatternPos
BLO.S mt_NoNewBlock
mt_NextPosition
MOVEQ #0,D0
MOVE.B mt_PBreakPos(PC),D0
LSL.W #4,D0
MOVE.W D0,mt_PatternPos
CLR.B mt_PBreakPos
CLR.B mt_PosJumpFlag
move.b mt_SongPos(pc),d1 ; Fixes and opts
addq.B #1,d1
and.B #$7F,d1
move.L mt_SongDataPtr(PC),A0
suba.w seqadj(pc),a0
move.b $3b6(a0),d2
cmp.b d2,d1
blo.s 1$
bsr intrepeat ; Signal when repeating
move.b $3b7(a0),d1
cmp.b d2,d1 ; < Fix - range check for song repeat
blo.s 1$
moveq #0,d1
1$ move.b d1,mt_SongPos
moveq #0,d0 ; Update MultiPlayer's position display
move.b d1,d0
moveq #0,d1
move.b d2,d1
jsr intsongpos
bsr.b findnotetab
mt_NoNewBlock
move.w mt_PatternPos(pc),d0 ; Update the scrolling note display
lsr.w #4,d0
moveq #64,d1
jsr intflashscroll
mt_NoNewPosYet
TST.B mt_PosJumpFlag
BNE mt_NextPosition
mt_exit movem.l (sp)+,d0-d7/a0-a6
RTS
findnotetab
MOVE.L mt_SongDataPtr(PC),A0 ; Find the new note table
LEA 952(A0),A2
suba.w seqadj(pc),a2
LEA 1084(A0),A0
suba.w blkadj(pc),a0
MOVE.B 0(A2,D0.W),D1
ASL.L #8,D1
ASL.L #2,D1
add.l d1,a0
move.l a0,notetab
rts
mt_CheckEfx
BSR mt_UpdateFunk
MOVE.W n_cmd(A6),D0
AND.W #$0FFF,D0
BEQ.S mt_PerNop
MOVE.B n_cmd(A6),D0
AND.B #$0F,D0
BEQ mt_Arpeggio
CMP.B #1,D0
BEQ mt_PortaUp
CMP.B #2,D0
BEQ mt_PortaDown
CMP.B #3,D0
BEQ mt_TonePortamento
CMP.B #4,D0
BEQ mt_Vibrato
CMP.B #5,D0
BEQ mt_TonePlusVolSlide
CMP.B #6,D0
BEQ mt_VibratoPlusVolSlide
CMP.B #$E,D0
BEQ mt_E_Commands
SetBack move.w d0,-(sp)
move.w n_period(a6),d0
useper
move.w (sp)+,d0
CMP.B #7,D0
BEQ mt_Tremolo
CMP.B #$A,D0
BEQ mt_VolumeSlide
mt_Return2
RTS
mt_PerNop
move.w n_period(a6),d0
useper
RTS
*** mt_Arpeggio - Process arpeggio commands (off-cycles)
mt_Arpeggio
MOVEQ #0,D7
MOVE.B mt_counter(PC),D7
divu.w #3,D7
swap d7
subq.w #1,d7
blo.s \mt_Arpeggio2
bhi.S \mt_Arpeggio1
MOVE.B n_cmdlo(A6),D7
LSR.B #4,D7
BRA.S \mt_Arpeggio3
\mt_Arpeggio1
MOVE.B n_cmdlo(A6),D7
AND.w #$f,D7
BRA.S \mt_Arpeggio3
\mt_Arpeggio2
MOVE.W n_period(A6),D0
BRA.S \mt_Arpeggio4
\mt_Arpeggio3
add.w d7,d7
MOVEQ #0,D1
MOVE.B n_finetune(A6),D1
MULU #36*2,D1
LEA mt_PeriodTable(PC),A0
ADD.w D1,A0
MOVEQ #0,D1
MOVE.W n_period(A6),D1
MOVEQ #36,D6
\mt_arploop
CMP.W (A0)+,D1
BHS.S \mt_Arpeggio4a
DBRA D6,\mt_arploop
RTS
\mt_Arpeggio4a
MOVE.W -2(A0,D7.W),D0
\mt_Arpeggio4
useper
RTS
mt_FinePortaUp
TST.B mt_counter
BNE mt_Return2
MOVE.B #$0F,mt_LowMask
mt_PortaUp
MOVEQ #0,D0
MOVE.B n_cmdlo(A6),D0
AND.B mt_LowMask(PC),D0
MOVE.B #$FF,mt_LowMask
SUB.W D0,n_period(A6)
MOVE.W n_period(A6),D0
AND.W #$0FFF,D0
CMP.W #113,D0
BPL.S mt_PortaUskip
AND.W #$F000,n_period(A6)
OR.W #113,n_period(A6)
mt_PortaUskip
MOVE.W n_period(A6),D0
AND.W #$0FFF,D0
useper
RTS
mt_FinePortaDown
TST.B mt_counter
BNE mt_Return2
MOVE.B #$0F,mt_LowMask
mt_PortaDown
CLR.W D0
MOVE.B n_cmdlo(A6),D0
AND.B mt_LowMask(PC),D0
MOVE.B #$FF,mt_LowMask
ADD.W D0,n_period(A6)
MOVE.W n_period(A6),D0
AND.W #$0FFF,D0
CMP.W #856,D0
BMI.S mt_PortaDskip
AND.W #$F000,n_period(A6)
OR.W #856,n_period(A6)
mt_PortaDskip
MOVE.W n_period(A6),D0
AND.W #$0FFF,D0
useper
RTS
mt_SetTonePorta
MOVE.L A0,-(SP)
MOVE.W (A6),D2
AND.W #$0FFF,D2
MOVEQ #0,D0
MOVE.B n_finetune(A6),D0
MULU #36*2,D0
LEA mt_PeriodTable(PC),A0
ADD.L D0,A0
MOVEQ #0,D0
mt_StpLoop
CMP.W 0(A0,D0.W),D2
BHS.S mt_StpFound
ADDQ.W #2,D0
CMP.W #36*2,D0
BLO.S mt_StpLoop
MOVEQ #35*2,D0
mt_StpFound
MOVE.B n_finetune(A6),D2
AND.B #8,D2
BEQ.S mt_StpGoss
TST.W D0
BEQ.S mt_StpGoss
SUBQ.W #2,D0
mt_StpGoss
MOVE.W 0(A0,D0.W),D2
MOVE.L (SP)+,A0
MOVE.W D2,n_wantedperiod(A6)
MOVE.W n_period(A6),D0
CLR.B n_toneportdirec(A6)
CMP.W D0,D2
BEQ.S mt_ClearTonePorta
BGE mt_Return2
MOVE.B #1,n_toneportdirec(A6)
RTS
mt_ClearTonePorta
CLR.W n_wantedperiod(A6)
RTS
mt_TonePortamento
MOVE.B n_cmdlo(A6),D0
BEQ.S mt_TonePortNoChange
MOVE.B D0,n_toneportspeed(A6)
CLR.B n_cmdlo(A6)
mt_TonePortNoChange
TST.W n_wantedperiod(A6)
BEQ mt_Return2
MOVEQ #0,D0
MOVE.B n_toneportspeed(A6),D0
TST.B n_toneportdirec(A6)
BNE.S mt_TonePortaUp
mt_TonePortaDown
ADD.W D0,n_period(A6)
MOVE.W n_wantedperiod(A6),D0
CMP.W n_period(A6),D0
BGT.S mt_TonePortaSetPer
MOVE.W n_wantedperiod(A6),n_period(A6)
CLR.W n_wantedperiod(A6)
BRA.S mt_TonePortaSetPer
mt_TonePortaUp
SUB.W D0,n_period(A6)
MOVE.W n_wantedperiod(A6),D0
CMP.W n_period(A6),D0
BLT.S mt_TonePortaSetPer
MOVE.W n_wantedperiod(A6),n_period(A6)
CLR.W n_wantedperiod(A6)
mt_TonePortaSetPer
MOVE.W n_period(A6),D2
MOVE.B n_glissfunk(A6),D0
AND.B #$0F,D0
BEQ.S mt_GlissSkip
MOVEQ #0,D0
MOVE.B n_finetune(A6),D0
MULU #36*2,D0
LEA mt_PeriodTable(PC),A0
ADD.L D0,A0
MOVEQ #0,D0
mt_GlissLoop
CMP.W 0(A0,D0.W),D2
BHS.S mt_GlissFound
ADDQ.W #2,D0
CMP.W #36*2,D0
BLO.S mt_GlissLoop
MOVEQ #35*2,D0
mt_GlissFound
MOVE.W 0(A0,D0.W),D2
mt_GlissSkip
move.w d2,d0
useper
RTS
mt_Vibrato
MOVE.B n_cmdlo(A6),D0
BEQ.S mt_Vibrato2
MOVE.B n_vibratocmd(A6),D2
AND.B #$0F,D0
BEQ.S mt_vibskip
AND.B #$F0,D2
OR.B D0,D2
mt_vibskip
MOVE.B n_cmdlo(A6),D0
AND.B #$F0,D0
BEQ.S mt_vibskip2
AND.B #$0F,D2
OR.B D0,D2
mt_vibskip2
MOVE.B D2,n_vibratocmd(A6)
mt_Vibrato2
MOVE.B n_vibratopos(A6),D0
LEA mt_VibratoTable(PC),A4
LSR.W #2,D0
AND.W #$001F,D0
MOVEQ #0,D2
MOVE.B n_wavecontrol(A6),D2
AND.B #$03,D2
BEQ.S mt_vib_sine
LSL.B #3,D0
CMP.B #1,D2
BEQ.S mt_vib_rampdown
MOVE.B #255,D2
BRA.S mt_vib_set
mt_vib_rampdown
TST.B n_vibratopos(A6)
BPL.S mt_vib_rampdown2
MOVE.B #255,D2
SUB.B D0,D2
BRA.S mt_vib_set
mt_vib_rampdown2
MOVE.B D0,D2
BRA.S mt_vib_set
mt_vib_sine
MOVE.B 0(A4,D0.W),D2
mt_vib_set
MOVE.B n_vibratocmd(A6),D0
AND.W #15,D0
MULU D0,D2
LSR.W #7,D2
MOVE.W n_period(A6),D0
TST.B n_vibratopos(A6)
BMI.S mt_VibratoNeg
ADD.W D2,D0
BRA.S mt_Vibrato3
mt_VibratoNeg
SUB.W D2,D0
mt_Vibrato3
useper
MOVE.B n_vibratocmd(A6),D0
LSR.W #2,D0
AND.W #$003C,D0
ADD.B D0,n_vibratopos(A6)
RTS
mt_TonePlusVolSlide
BSR mt_TonePortNoChange
BRA mt_VolumeSlide
mt_VibratoPlusVolSlide
BSR mt_Vibrato2
BRA mt_VolumeSlide
mt_Tremolo
MOVE.B n_cmdlo(A6),D0
BEQ.S mt_Tremolo2
MOVE.B n_tremolocmd(A6),D2
AND.B #$0F,D0
BEQ.S mt_treskip
AND.B #$F0,D2
OR.B D0,D2
mt_treskip
MOVE.B n_cmdlo(A6),D0
AND.B #$F0,D0
BEQ.S mt_treskip2
AND.B #$0F,D2
OR.B D0,D2
mt_treskip2
MOVE.B D2,n_tremolocmd(A6)
mt_Tremolo2
MOVE.B n_tremolopos(A6),D0
LEA mt_VibratoTable(PC),A4
LSR.W #2,D0
AND.W #$001F,D0
MOVEQ #0,D2
MOVE.B n_wavecontrol(A6),D2
LSR.B #4,D2
AND.B #$03,D2
BEQ.S mt_tre_sine
LSL.B #3,D0
CMP.B #1,D2
BEQ.S mt_tre_rampdown
MOVE.B #255,D2
BRA.S mt_tre_set
mt_tre_rampdown
TST.B n_vibratopos(A6)
BPL.S mt_tre_rampdown2
MOVE.B #255,D2
SUB.B D0,D2
BRA.S mt_tre_set
mt_tre_rampdown2
MOVE.B D0,D2
BRA.S mt_tre_set
mt_tre_sine
MOVE.B 0(A4,D0.W),D2
mt_tre_set
MOVE.B n_tremolocmd(A6),D0
AND.W #15,D0
MULU D0,D2
LSR.W #6,D2
MOVEQ #0,D0
MOVE.B n_volume(A6),D0
TST.B n_tremolopos(A6)
BMI.S mt_TremoloNeg
ADD.W D2,D0
BRA.S mt_Tremolo3
mt_TremoloNeg
SUB.W D2,D0
mt_Tremolo3
BPL.S mt_TremoloSkip
CLR.W D0
mt_TremoloSkip
CMP.W #$40,D0
BLS.S mt_TremoloOk
MOVE.W #$40,D0
mt_TremoloOk
usevol
MOVE.B n_tremolocmd(A6),D0
LSR.W #2,D0
AND.W #$003C,D0
ADD.B D0,n_tremolopos(A6)
RTS
mt_SampleOffset
MOVEQ #0,D0
MOVE.B n_cmdlo(A6),D0
BEQ.S mt_sononew
MOVE.B D0,n_sampleoffset(A6)
mt_sononew
MOVE.B n_sampleoffset(A6),D0
LSL.W #7,D0
CMP.W n_length(A6),D0
BGE.S mt_sofskip
SUB.W D0,n_length(A6)
LSL.W #1,D0
ADD.L D0,n_start(A6)
RTS
mt_sofskip
MOVE.W #$0001,n_length(A6)
RTS
*** mt_VolumeSlide ($A), mt_VolumeFineUp ($EA), mt_VolumeFineDown ($EB)
mt_VolumeSlide
MOVEQ #0,D0
MOVE.B n_cmdlo(A6),D0
LSR.B #4,D0
BEQ.S vol_VolSlideDown
vol_VolSlideUp
ADD.B n_volume(A6),d0
CMP.B #$40,d0
bls.S \mt_vsuskip
moveq #$40,d0
\mt_vsuskip
MOVE.B d0,n_volume(A6)
bra vol_set
mt_VolumeFineUp
TST.B mt_counter
BNE mt_Return2
MOVE.B n_cmdlo(A6),D0
and.w #$F,D0
BRA vol_VolSlideUp
vol_VolSlideDown
MOVE.B n_cmdlo(A6),D0
AND.w #$0F,D0
vol_VolSlideDown2
SUB.B D0,n_volume(A6)
bhs.S \mt_vsdskip
CLR.B n_volume(A6)
\mt_vsdskip
MOVE.B n_volume(A6),d0
vol_set
usevol
RTS
mt_VolumeFineDown
TST.B mt_counter
BNE mt_Return2
MOVE.B n_cmdlo(A6),D0
AND.w #$0F,D0
BRA vol_VolSlideDown2
mt_PositionJump
MOVE.B n_cmdlo(A6),D0
cmp.b mt_SongPos(pc),d0 ; Check for repeat
bhi.s 1$
jsr intrepeat
1$
SUBQ.B #1,D0
MOVE.B D0,mt_SongPos
mt_pj2 CLR.B mt_PBreakPos
ST mt_PosJumpFlag
RTS
*** mt_VolumeChange - Effect $C, on-cycles
mt_VolumeChange
MOVEQ #0,D0
MOVE.B n_cmdlo(A6),D0
CMP.B #$40,D0
BLS.S \mt_VolumeOk
MOVEQ #$40,D0
\mt_VolumeOk
MOVE.B D0,n_volume(A6)
usevol
RTS
mt_PatternBreak
MOVEQ #0,D0
MOVE.B n_cmdlo(A6),D0
MOVE.L D0,D2
LSR.B #4,D0
MULU #10,D0
AND.B #$0F,D2
ADD.B D2,D0
CMP.B #63,D0
BHI.S mt_pj2
MOVE.B D0,mt_PBreakPos
ST mt_PosJumpFlag
RTS
mt_SetSpeed
MOVEQ #0,D0
MOVE.B 3(A6),D0
BEQ \out
CMP.B #$20,D0
blo.b \normal
btst.b #MNB_PTTEMPO,modflags
bnz SetTempo
\normal
CLR.B mt_counter
MOVE.B D0,mt_speed
\out
RTS
mt_CheckMoreEfx
BSR mt_UpdateFunk
MOVE.B 2(A6),D0
AND.B #$0F,D0
CMP.B #$9,D0
BEQ mt_SampleOffset
CMP.B #$B,D0
BEQ mt_PositionJump
CMP.B #$D,D0
BEQ mt_PatternBreak
CMP.B #$E,D0
BEQ.S mt_E_Commands
CMP.B #$F,D0
BEQ.S mt_SetSpeed
CMP.B #$C,D0
BEQ mt_VolumeChange
BRA mt_PerNop
mt_E_Commands
MOVE.B n_cmdlo(A6),D0
AND.B #$F0,D0
LSR.B #4,D0
BEQ.S mt_FilterOnOff
CMP.B #1,D0
BEQ mt_FinePortaUp
CMP.B #2,D0
BEQ mt_FinePortaDown
CMP.B #3,D0
BEQ mt_SetGlissControl
CMP.B #4,D0
BEQ mt_SetVibratoControl
CMP.B #5,D0
BEQ mt_SetFineTune
CMP.B #6,D0
BEQ mt_JumpLoop
CMP.B #7,D0
BEQ mt_SetTremoloControl
CMP.B #9,D0
BEQ mt_RetrigNote
CMP.B #$A,D0
BEQ mt_VolumeFineUp
CMP.B #$B,D0
BEQ mt_VolumeFineDown
CMP.B #$C,D0
BEQ mt_NoteCut
CMP.B #$D,D0
BEQ mt_NoteDelay
CMP.B #$E,D0
BEQ mt_PatternDelay
CMP.B #$F,D0
BEQ mt_FunkIt
RTS
mt_FilterOnOff
MOVE.B n_cmdlo(A6),D0
AND.B #1,D0
initfilter
move.b d0,modfilter
setfilter
tst.b filter
ble.b \modcontrol
moveq #2,d0
sub.b filter,d0
\modcontrol
add.b d0,d0
and.b #2,d0
AND.B #$FD,$BFE001
OR.B D0,$BFE001
RTS
ptfilter
tst.b playing
bz mt_Return2
move.b modfilter(pc),d0
bra.b setfilter
mt_SetGlissControl
MOVE.B n_cmdlo(A6),D0
AND.B #$0F,D0
AND.B #$F0,n_glissfunk(A6)
OR.B D0,n_glissfunk(A6)
RTS
mt_SetVibratoControl
MOVE.B n_cmdlo(A6),D0
AND.B #$0F,D0
AND.B #$F0,n_wavecontrol(A6)
OR.B D0,n_wavecontrol(A6)
RTS
mt_SetFineTune
MOVE.B n_cmdlo(A6),D0
AND.B #$0F,D0
MOVE.B D0,n_finetune(A6)
RTS
mt_JumpLoop
TST.B mt_counter
BNE mt_Return2
MOVE.B n_cmdlo(A6),D0
AND.B #$0F,D0
BEQ.S mt_SetLoop
TST.B n_loopcount(A6)
BEQ.S mt_jumpcnt
SUBQ.B #1,n_loopcount(A6)
BEQ mt_Return2
mt_jmploop
MOVE.B n_pattpos(A6),mt_PBreakPos
ST mt_PBreakFlag
RTS
mt_jumpcnt
MOVE.B D0,n_loopcount(A6)
BRA.S mt_jmploop
mt_SetLoop
MOVE.W mt_PatternPos(PC),D0
LSR.W #4,D0
MOVE.B D0,n_pattpos(A6)
RTS
mt_SetTremoloControl
MOVE.B n_cmdlo(A6),D0
AND.B #$0F,D0
LSL.B #4,D0
AND.B #$0F,n_wavecontrol(A6)
OR.B D0,n_wavecontrol(A6)
RTS
mt_RetrigNote
MOVE.L D1,-(SP)
MOVEQ #0,D0
MOVE.B n_cmdlo(A6),D0
AND.B #$0F,D0
BEQ.S mt_rtnend
MOVEQ #0,D1
MOVE.B mt_counter(PC),D1
BNE.S mt_rtnskp
MOVE.W (A6),D1
AND.W #$0FFF,D1
BNE.S mt_rtnend
MOVEQ #0,D1
MOVE.B mt_counter(PC),D1
mt_rtnskp
DIVU D0,D1
SWAP D1
TST.W D1
BNE.S mt_rtnend
mt_DoRetrig
movem.l d2-d4/a0-a1,-(sp)
move.l n_start(a6),a0
moveq #0,d0
move.w n_length(a6),d0
add.l d0,d0
move.l n_loopstart(a6),a1
moveq #0,d1
move.w n_replen(a6),d1
cmp.w #1,d1
bne.b \notone
moveq #0,d1
\notone
add.l d1,d1
move.w n_channelno(a6),d2
moveq #0,d3
move.w n_period(a6),d3
move.w d3,n_realper(a6)
swap d3
moveq #0,d4
move.b n_volume(a6),d4
move.w d4,n_realvol(a6)
lsl.w #2,d4
jsr NoteStart(a5)
movem.l (sp)+,d2-d4/a0-a1
mt_rtnend
MOVE.L (SP)+,D1
RTS
mt_NoteCut
MOVEQ #0,D0
MOVE.B n_cmdlo(A6),D0
AND.B #$0F,D0
CMP.B mt_counter(PC),D0
BNE mt_Return2
CLR.B n_volume(A6)
moveq #0,d0
usevol
RTS
mt_NoteDelay
MOVEQ #0,D0
MOVE.B n_cmdlo(A6),D0
AND.B #$0F,D0
CMP.B mt_counter,D0
BNE mt_Return2
MOVE.W (A6),D0
BEQ mt_Return2
MOVE.L D1,-(SP)
BRA mt_DoRetrig
mt_PatternDelay
TST.B mt_counter
BNE mt_Return2
MOVEQ #0,D0
MOVE.B n_cmdlo(A6),D0
AND.B #$0F,D0
TST.B mt_PattDelTime2
BNE mt_Return2
ADDQ.B #1,D0
MOVE.B D0,mt_PattDelTime
RTS
mt_FunkIt
TST.B mt_counter
BNE mt_Return2
MOVE.B n_cmdlo(A6),D0
AND.B #$0F,D0
LSL.B #4,D0
AND.B #$0F,n_glissfunk(A6)
OR.B D0,n_glissfunk(A6)
TST.B D0
BEQ mt_Return2
mt_UpdateFunk
MOVEM.L D1/A0,-(SP)
MOVEQ #0,D0
MOVE.B n_glissfunk(A6),D0
LSR.B #4,D0
BEQ.S mt_funkend
LEA mt_FunkTable(PC),A0
MOVE.B 0(A0,D0.W),D0
ADD.B D0,n_funkoffset(A6)
BTST #7,n_funkoffset(A6)
BEQ.S mt_funkend
CLR.B n_funkoffset(A6)
MOVE.L n_loopstart(A6),D0
MOVEQ #0,D1
MOVE.W n_replen(A6),D1
ADD.L D1,D0
ADD.L D1,D0
MOVE.L n_wavestart(A6),A0
ADDQ.L #1,A0
CMP.L D0,A0
BLO.S mt_funkok
MOVE.L n_loopstart(A6),A0
mt_funkok
MOVE.L A0,n_wavestart(A6)
MOVEQ #-1,D0
SUB.B (A0),D0
MOVE.B D0,(A0)
mt_funkend
MOVEM.L (SP)+,D1/A0
RTS
SetTempo
push a0/d0/d1
move.w d0,d1
move.l 4,a0
move.l #1789773,d0
cmp.b #50,PowerSupplyFrequency(a0)
bne.s 2$
move.l #1773447,d0
2$ divu.w d1,d0
bsr changetintcia
pop a0/d0/d1
rts
mt_FunkTable dc.b 0,5,6,7,8,10,11,13,16,19,22,26,32,43,64,128
mt_VibratoTable
dc.b 0,24,49,74,97,120,141,161
dc.b 180,197,212,224,235,244,250,253
dc.b 255,253,250,244,235,224,212,197
dc.b 180,161,141,120,97,74,49,24
mt_PeriodTable
; Tuning 0, Normal
dc.w 856,808,762,720,678,640,604,570,538,508,480,453
dc.w 428,404,381,360,339,320,302,285,269,254,240,226
dc.w 214,202,190,180,170,160,151,143,135,127,120,113
; Tuning 1
dc.w 850,802,757,715,674,637,601,567,535,505,477,450
dc.w 425,401,379,357,337,318,300,284,268,253,239,225
dc.w 213,201,189,179,169,159,150,142,134,126,119,113
; Tuning 2
dc.w 844,796,752,709,670,632,597,563,532,502,474,447
dc.w 422,398,376,355,335,316,298,282,266,251,237,224
dc.w 211,199,188,177,167,158,149,141,133,125,118,112
; Tuning 3
dc.w 838,791,746,704,665,628,592,559,528,498,470,444
dc.w 419,395,373,352,332,314,296,280,264,249,235,222
dc.w 209,198,187,176,166,157,148,140,132,125,118,111
; Tuning 4
dc.w 832,785,741,699,660,623,588,555,524,495,467,441
dc.w 416,392,370,350,330,312,294,278,262,247,233,220
dc.w 208,196,185,175,165,156,147,139,131,124,117,110
; Tuning 5
dc.w 826,779,736,694,655,619,584,551,520,491,463,437
dc.w 413,390,368,347,328,309,292,276,260,245,232,219
dc.w 206,195,184,174,164,155,146,138,130,123,116,109
; Tuning 6
dc.w 820,774,730,689,651,614,580,547,516,487,460,434
dc.w 410,387,365,345,325,307,290,274,258,244,230,217
dc.w 205,193,183,172,163,154,145,137,129,122,115,109
; Tuning 7
dc.w 814,768,725,684,646,610,575,543,513,484,457,431
dc.w 407,384,363,342,323,305,288,272,256,242,228,216
dc.w 204,192,181,171,161,152,144,136,128,121,114,108
; Tuning -8
dc.w 907,856,808,762,720,678,640,604,570,538,508,480
dc.w 453,428,404,381,360,339,320,302,285,269,254,240
dc.w 226,214,202,190,180,170,160,151,143,135,127,120
; Tuning -7
dc.w 900,850,802,757,715,675,636,601,567,535,505,477
dc.w 450,425,401,379,357,337,318,300,284,268,253,238
dc.w 225,212,200,189,179,169,159,150,142,134,126,119
; Tuning -6
dc.w 894,844,796,752,709,670,632,597,563,532,502,474
dc.w 447,422,398,376,355,335,316,298,282,266,251,237
dc.w 223,211,199,188,177,167,158,149,141,133,125,118
; Tuning -5
dc.w 887,838,791,746,704,665,628,592,559,528,498,470
dc.w 444,419,395,373,352,332,314,296,280,264,249,235
dc.w 222,209,198,187,176,166,157,148,140,132,125,118
; Tuning -4
dc.w 881,832,785,741,699,660,623,588,555,524,494,467
dc.w 441,416,392,370,350,330,312,294,278,262,247,233
dc.w 220,208,196,185,175,165,156,147,139,131,123,117
; Tuning -3
dc.w 875,826,779,736,694,655,619,584,551,520,491,463
dc.w 437,413,390,368,347,328,309,292,276,260,245,232
dc.w 219,206,195,184,174,164,155,146,138,130,123,116
; Tuning -2
dc.w 868,820,774,730,689,651,614,580,547,516,487,460
dc.w 434,410,387,365,345,325,307,290,274,258,244,230
dc.w 217,205,193,183,172,163,154,145,137,129,122,115
; Tuning -1
dc.w 862,814,768,725,684,646,610,575,543,513,484,457
dc.w 431,407,384,363,342,323,305,288,272,256,242,228
dc.w 216,203,192,181,171,161,152,144,136,128,121,114
mt_chan1temp dc.l 0,0,0,0,0,$00010000,0,0,0,0,0,0
mt_chan2temp dc.l 0,0,0,0,0,$00020000,0,0,0,0,1,0
mt_chan3temp dc.l 0,0,0,0,0,$00040000,0,0,0,0,2,0
mt_chan4temp dc.l 0,0,0,0,0,$00080000,0,0,0,0,3,0
mt_SampleStarts dc.l 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
dc.l 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
mt_SongDataPtr dc.l 0
scroll dc.l 0
noteplayer dc.l 0
mt_PatternPos dc.w 0
mt_DMACONtemp dc.w 0
seqadj dc.w 0 ; < Fix - for old modules
blkadj dc.w 0
mt_speed dc.b 0
mt_counter dc.b 0
mt_SongPos dc.b 0
mt_PBreakPos dc.b 0
mt_PosJumpFlag dc.b 0
mt_PBreakFlag dc.b 0
mt_LowMask dc.b 0
mt_PattDelTime dc.b 0
mt_PattDelTime2 dc.b 0,0
modfilter dc.b 0
playing dc.b 0
name dc.b "Sound/Noise/ProTracker",0
end